/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.rafkind.raytracer;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author drafkind
 */
public class Sphere extends VisibleObject {
  private Vector3 position;
  private double radius;

  public Sphere() {
  }


  public List<IntersectionPoint> getIntersectionPoints(Ray ray) {
    List<IntersectionPoint> points = new ArrayList<IntersectionPoint>();

    Vector3 oMinusC = ray.getPosition().minus(position);
    double A = ray.getDirection().dot(ray.getDirection());
    double B = 2 * oMinusC.dot(ray.getDirection());
    double C = oMinusC.dot(oMinusC) - radius * radius;

    double determinant = B * B - (4 * A * C);
    if (determinant >= 0) {

      double sqd = Math.sqrt(determinant);
      double t1 = (-B + sqd) / (2 * A);
      double t2 = (-B - sqd) / (2 * A);

      if (t1 > 0) {
        Vector3 p = ray.getPosition().plus(ray.getDirection().times(t1));
        points.add(new IntersectionPoint(p, p.getDistanceTo(ray.getPosition()), this));
      }
      if (t2 > 0) {
        Vector3 p = ray.getPosition().plus(ray.getDirection().times(t2));
        points.add(new IntersectionPoint(p, p.getDistanceTo(ray.getPosition()), this));
      }
    }

    return points;
  }

  @Override public boolean isInsideImplementation(Vector3 where) {
    return where.getDistanceTo(position) <= radius;
  }

  public Vector3 getPosition() {
    return position;
  }

  public void setPosition(Vector3 position) {
    this.position = position;
  }

  public double getRadius() {
    return radius;
  }

  public void setRadius(double radius) {
    this.radius = radius;
  }

  public Vector3 getNormalAt(IntersectionPoint where) {
    return where.getPoint().minus(position).getNormalized();
  }
}
